home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / 68kdis.zip / ROBJ.C < prev    next >
C/C++ Source or Header  |  1988-12-03  |  18KB  |  859 lines

  1. /*
  2.  *    SCCS:    @(#)robj.c    1.2    11/2/84    14:19:59
  3.  *    Read object files.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  *
  25.  *    This particular module will obviously have to be munged beyond
  26.  *    recognition for another object format.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <a.out.h>
  31. #include <ldfcn.h>
  32. #include <string.h>
  33. #include "unc.h"
  34.  
  35. void    gette(), getde(), setde(), putte(), putde();
  36. long    gettw(), getdw();
  37. void    reallst(), lclash(), nomem(), unimpl();
  38. void    addit();
  39. char    *malloc();
  40. long    lseek();
  41.  
  42. int    par_entry, par_round, nmods, donedrel, donebrel;
  43. struct    commit    abstab, comtab, dreltab;
  44. long    trelpos, drelpos, brelpos;
  45.  
  46. int *symord;    /* convert symbol index to symbol ordinal */
  47.  
  48. ef_fids    mainfile;
  49.  
  50. symbol    lookup(), inventsymb(), getnsymb();
  51.  
  52. #define RWORD 1
  53. #define RLONG 2
  54. #define    DBSIZE    100
  55. #define    STINIT    20
  56.  
  57. /*
  58.  *    Read text segment.  Return 0 if not ok.
  59.  */
  60.  
  61. int    rtext(ldptr, outf)
  62.   LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  63.   ef_fid    outf;        /*  Output file descriptor  */
  64. {
  65.    t_entry        tstr;
  66.    struct    aouthdr    unixhdr;
  67.    struct  scnhdr  sect;
  68.    register  long    size;
  69.    register  int    i, l;
  70.    unsigned  short    inbuf[DBSIZE/2];
  71.    
  72.    /*
  73.     *    Initialise fields in structure.
  74.     */
  75.    
  76.    tstr.t_type = T_UNKNOWN;
  77.    tstr.t_vins = 1;        /*  For the moment  */
  78.    tstr.t_bdest = 0;
  79.    tstr.t_gbdest = 0;
  80.    tstr.t_lng = 1;
  81.    tstr.t_reloc = R_NONE;
  82.    tstr.t_rdisp = 0;
  83.    tstr.t_isrel = 0;
  84.    tstr.t_amap = 0;
  85.     tstr.t_dref = 0;
  86.     tstr.t_relsymb = NULL;
  87.     tstr.t_reldisp = 0;
  88.     tstr.t_lab = NULL;
  89.     tstr.t_lsymb = 0;
  90.     tstr.t_refhi = 0;
  91.     tstr.t_reflo = 0x7fffffff;
  92.     tstr.t_match = 0;
  93.     
  94.     /*
  95.      *    Read a.out header.
  96.      */
  97.  
  98.     if (ldohseek(ldptr) == FAILURE) {    /* no optional header */
  99.  
  100.         outf->ef_entry = 0;
  101.         ldshread(ldptr,1,§);        /* text header */
  102.         outf->ef_tbase = sect.s_vaddr;
  103.         outf->ef_tsize = sect.s_size;
  104.  
  105.         ldshread(ldptr,2,§);        /* data header */
  106.         outf->ef_dbase = sect.s_vaddr;
  107.         outf->ef_dsize = sect.s_size;
  108.  
  109.         ldshread(ldptr,3,§);        /* bss header */
  110.         outf->ef_bbase = sect.s_vaddr;
  111.         outf->ef_bsize = sect.s_size;
  112.         outf->ef_end = sect.s_vaddr + sect.s_size;
  113.     } else {
  114.         FREAD((char *)&unixhdr,sizeof(struct aouthdr),1,ldptr);
  115.     
  116.         if ( N_BADMAG(unixhdr) )
  117.         return    0;
  118.  
  119.         outf->ef_entry = unixhdr.entry;
  120.         outf->ef_tbase = unixhdr.text_start;
  121.         outf->ef_dbase = unixhdr.data_start;
  122.         outf->ef_bbase = outf->ef_dbase + unixhdr.dsize;
  123.         outf->ef_end = outf->ef_bbase + unixhdr.bsize;
  124.  
  125.         outf->ef_tsize = unixhdr.tsize;
  126.         outf->ef_dsize = unixhdr.dsize;
  127.         outf->ef_bsize = unixhdr.bsize;
  128.     }
  129.     
  130.     ldsseek(ldptr,1);    /* seek to text section */
  131.     
  132.     size = outf->ef_tsize;
  133.     
  134.     while  (size > 1)  {
  135.         l = size > DBSIZE? DBSIZE: size;
  136.         if  (FREAD((char *)inbuf,1,l,ldptr) != l)
  137.             return    0;
  138.         l /= 2;
  139.         for  (i = 0;  i < l;  i++)  {
  140.             tstr.t_contents = inbuf[i];
  141.             (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  142.         }
  143.         size -= l + l;
  144.     }
  145.     
  146.     /*
  147.      *    Extra one to cope with "etext".
  148.      */
  149.     
  150.     (void) write(outf->ef_t, (char *)&tstr, sizeof(tstr));
  151.     return    1;
  152. }
  153. /*
  154.  *    Same sort of thing for the data segment.
  155.  */
  156.  
  157. int    rdata(ldptr, outf)
  158. LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  159. ef_fid    outf;        /*  Output file descriptor  */
  160. {
  161.     d_entry        dstr;
  162.     register  long    size;
  163.     register  int    i, l;
  164.     unsigned  char    inbuf[DBSIZE];
  165.  
  166.     /*
  167.      *    Initialise fields in structure.
  168.      */
  169.     
  170.     dstr.d_type = D_BYTE;
  171.     dstr.d_reloc = R_NONE;
  172.     dstr.d_lng = 1;
  173.     dstr.d_relsymb = NULL;
  174.     dstr.d_reldisp = 0;
  175.     dstr.d_lab = NULL;
  176.     
  177.     ldsseek(ldptr,2);    /* seek to data section */
  178.     
  179.     size = outf->ef_dsize;
  180.     
  181.     while  (size > 0)  {
  182.         l = size > DBSIZE? DBSIZE: size;
  183.         if  (FREAD((char *)inbuf,1,l,ldptr) != l)
  184.             return    0;
  185.         for  (i = 0;  i < l;  i++)  {
  186.             dstr.d_contents = inbuf[i];
  187.             (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  188.         }
  189.         size -= l;
  190.     }
  191.     
  192.     /*
  193.      *    Repeat for BSS segment.
  194.      */
  195.  
  196.     dstr.d_contents = 0;
  197.     for  (size = outf->ef_bsize;  size > 0;  size--)
  198.         (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  199.     
  200.     /*
  201.      *    Extra one to cope with "end".
  202.      */
  203.     
  204.     (void) write(outf->ef_d, (char *)&dstr, sizeof(dstr));
  205.     return    1;
  206. }
  207.  
  208. /*
  209.  *    Process symbol table segment.
  210.  */
  211.  
  212. int    rsymb(ldptr, dproc, outf)
  213. LDFILE *ldptr;        /*  a.out file (possibly in library)  */
  214. symbol    (*dproc)();
  215. register  ef_fid  outf;    /*  Output file descriptor  */
  216. {
  217. #define SYMLENGTH 256
  218.     register  symbol  csym;
  219.      struct    syment    isym;
  220.     register  int   nsyms,symindex;
  221.     unsigned long   stroff;
  222.      char    inbuf[SYMLENGTH+1], *cp;
  223.     int ord;
  224.  
  225.     nsyms = HEADER(ldptr).f_nsyms;
  226.     stroff = HEADER(ldptr).f_symptr + nsyms*sizeof(struct syment);
  227.  
  228.     if  (nsyms <= 0)
  229.         nsyms = STINIT;
  230.  
  231.     outf->ef_stvec = (symbol *) malloc(nsyms * sizeof(symbol));
  232.     symord = (int *) malloc(nsyms * sizeof(int));
  233.     if  (outf->ef_stvec == NULL)
  234.         nomem();
  235.  
  236.     outf->ef_stcnt = 0;
  237.     outf->ef_stmax = nsyms;
  238.     ord = 0;
  239.     
  240.      for  (symindex=0; symindex<nsyms; symindex++)  {
  241.         ldtbread(ldptr,symindex,&isym);
  242.         if (isym.n_zeroes == 0) {    /* get from string table */
  243.             FSEEK(ldptr,stroff + isym.n_offset,0);
  244.             cp = inbuf;
  245.             do {
  246.              if (FREAD(cp,1,1,ldptr) != 1)/* Read symbol chars 1-by-1 */
  247.                  return 0;
  248.              if ( cp - inbuf >= SYMLENGTH )/* Check against buffer overflow */
  249.                  return 0;
  250.             } while (*cp++ != '\0');/* Terminate on null byte */
  251.         } else {            /* get from symbol field */
  252.             strncpy(inbuf,isym.n_name,8);
  253.             inbuf[8] = '\0';
  254.         }
  255.          csym = (*dproc)(lookup(inbuf), convtosun(&isym),
  256.                 isym.n_value, outf);
  257.          if (outf->ef_stcnt >= outf->ef_stmax)
  258.             reallst(outf);
  259.         outf->ef_stvec[outf->ef_stcnt++] = csym;
  260.         symord[symindex] = ord++;        /* record ordinal */
  261.         symindex += isym.n_numaux;        /* skip aux entries */
  262.     }
  263.     return    1;
  264. }
  265.  
  266. /*
  267.  *    Process relocation stuff.  -1 error, 0 no relocation, 1 relocation.
  268.  */
  269.  
  270. int    rrel(ldptr, ldptr2, outf)
  271. LDFILE *ldptr,*ldptr2;    /*  a.out file (possibly in library)  */
  272. ef_fid    outf;        /*  Output file descriptor  */
  273. {
  274.      struct    reloc    crel;
  275.     struct scnhdr tsect,dsect;
  276.     struct syment isym;
  277.     t_entry    tstr;
  278.     d_entry    dstr;
  279.     register  int    nreloc;
  280.     long    cont, pos;
  281.  
  282.     ldshread(ldptr,1,&tsect);
  283.     ldshread(ldptr,2,&dsect);
  284.      if  (tsect.s_nreloc <= 0  &&  dsect.s_nreloc <= 0)
  285.         return    0;
  286.  
  287.     nreloc = tsect.s_nreloc;
  288.  
  289.     ldrseek(ldptr,1);
  290.      while  (nreloc-- > 0)  {
  291.         if  (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  292.             return    -1;
  293.  
  294.          pos = crel.r_vaddr;
  295.         gette(outf, pos, &tstr);
  296.         if (crel.r_type == R_ABS)
  297.             tstr.t_reloc = R_NONE;
  298.         else
  299.             tstr.t_reloc = R_LONG;    /* what about PC-relative? */
  300.         ldtbread(ldptr2,crel.r_symndx,&isym);
  301.         if (isym.n_sclass == C_EXT) {
  302.              tstr.t_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
  303.              tstr.t_reldisp = gettw(outf, pos, (int)tstr.t_reloc);
  304.         }
  305.         else  {
  306.              cont = gettw(outf, pos, (int)tstr.t_reloc);
  307.              tstr.t_relsymb = getnsymb(outf, convtosun(&isym), cont);
  308.         }
  309.         tstr.t_relsymb->s_used++;
  310.         putte(outf, pos, &tstr);
  311.     }
  312.     
  313.     /*
  314.      *    And now repeat all that for data relocations.
  315.      */
  316.     
  317.     nreloc = dsect.s_nreloc;
  318.     
  319.     ldrseek(ldptr,2);
  320.      while  (nreloc-- > 0)  {
  321.         if (FREAD((char *)&crel, sizeof(crel),1,ldptr) != 1)
  322.             return    -1;
  323.  
  324.          pos = crel.r_vaddr;
  325.         getde(outf, pos, &dstr);
  326.         if (crel.r_type == R_ABS)
  327.             dstr.d_reloc = R_NONE;
  328.         else
  329.             dstr.d_reloc = R_LONG;    /* what about PC-relative? */
  330.  
  331.         ldtbread(ldptr2,crel.r_symndx,&isym);
  332.         if (isym.n_sclass == C_EXT) {
  333.              dstr.d_relsymb = outf->ef_stvec[symord[crel.r_symndx]];
  334.              dstr.d_reldisp = getdw(outf, pos, (int)dstr.d_reloc);
  335.         }
  336.         else  {
  337.              cont = getdw(outf, pos, (int)dstr.d_reloc);
  338.              dstr.d_relsymb = getnsymb(outf, convtosun(&isym), cont);
  339.              if  (dstr.d_relsymb->s_type == S_TEXT)  {
  340.                 gette(outf, cont, &tstr);
  341.                 tstr.t_